package CreationPattern.Singleton;

/**
 * @Classname : CreationPattern.Singleton
 * @Description : 单例模式
 * 一、模式定义
 *   Ensure a class has only one instance, and provide a global point of access to it.
 *   （保证一个类只有一个实例对象，并提供一个获取该实例对象的全局访问点。）
 * 二、模式类图
 *   https://kdocs.cn/l/cozQKGDBWKJT
 * 三、适用场景
 *   1、要求生成唯一序列号的环境
 *   2、整个项目中需要一个共享访问点或共享数据，例如Web页面上的计数器，可以不用把每次刷新都记录到数据库，使用单例模式来维护计数器的值
 *   3、创建一个对象需要消耗的资源过多，如访问IO和数据库等资源
 *   4、需要大量静态常量和静态方法（如工具类）的环境，可以采用单例模式，也可以直接声明为static的方式
 *   5、除了对资源利用率要求不高时（单例对象占用资源少，不需要延时加载）可以选择枚举式，其他情况都建议选择静态内部类方式实现
 * 四、应用举例
 *   任务管理器、回收站、日志应用、操作系统的文件系统、网站计数器
 *   Spring容器中的每个Bean、数据库连接池、项目中读取配置文件的类、每个Servlet、Servlet中的application对象
 * @Author : chentianyu
 * @Date 2022/12/25 23:25
 */

/**
 * 饿汉式：类初始化时会立即加载这个对象
 * 优点：方法没有同步，调用效率高。
 * 缺点：可能出现对象被加载但一直没被使用的情况，如仅调用了类的静态方法，内存资源效率低。
 * 线程安全：类加载的过程虚拟机会保证线程安全。
 */
public class Singleton {
    // 组合方式产生一个实例
    private static final Singleton instance = new Singleton();

    // 限制产生多个对象
    private Singleton() {}

    // 通过该方法获取实例对象
    public static Singleton getInstance() {
        return instance;
    }

    // 类中其他方法，尽量是static
    public static void doSomething() {

    }
}


/**
 * 懒汉式-方法加锁同步：调用getInstance方法时才会加载对象
 * 优点：调用类其他静态方法不会创建单例对象，内存资源效率高。
 * 缺点：每次调用都需要加锁同步，调用效率低。
 * 线程安全：方法加锁同步，保证线程安全。
 */
class Singleton02 {
    private static Singleton02 instance;

    private Singleton02() {}

    public static synchronized Singleton02 getInstance() {
        if (instance == null) {
            instance = new Singleton02();
        }
        return instance;
    }
}


/**
 * 懒汉式-双重检查锁：调用getInstance方法时才会加载对象
 * 优点：调用类其他静态方法不会创建单例对象，内存资源效率高。
 * 缺点：每次调用都需要加锁同步，调用效率低。
 * 线程安全：类加锁同步，保证线程安全。
 */
class Singleton03 {
    private static Singleton03 instance;

    private Singleton03() {}

    public static Singleton03 getInstance() {
        if (instance == null) {
            Singleton03 s;
            synchronized (Singleton03.class) {
                s = instance;
                if (s == null) {
                    synchronized (Singleton03.class) {
                        if (s == null) {
                            s = new Singleton03();
                        }
                    }
                    instance = s;
                }
            }
        }
        return instance;
    }
}


/**
 * 静态内部类：调用getInstance方法时才会加载对象
 * 优点：方法没有同步，调用效率高；调用类其他静态方法不会创建单例对象，内存资源效率高。
 * 线程安全：类加载的过程虚拟机会保证线程安全。
 */
class Singleton04 {
    // 静态内部类实现延迟加载
    private static class SingletonInstance {
        private static Singleton04 instance = new Singleton04();
    }

    private Singleton04() {}

    public static Singleton04 getInstance() {
        // 调用时才会加载静态内部类
        return SingletonInstance.instance;
    }
}


/**
 * 枚举式：类初始化时会立即加载这个对象，类似饿汉式
 * 优点：方法没有同步，调用效率高。
 * 缺点：可能出现对象被加载但一直没被使用的情况，如仅调用了类的静态方法，内存资源效率低。
 * 线程安全：类加载的过程虚拟机会保证线程安全。
 */
enum Singleton05 {
    // 一个枚举元素本身就是单例对象
    INSTANCE;

    // 可像类中那样添加自己需要的方法
    public static void doSomething() {}
}
